//these are functions that interface with the locker object

#include "locker.h"
#include "key_generator.h"
#include <wiringPi.h>

/*
struct locker_pins usable_pins[] = {
    {11, 13, 15},
    {29, 31, 33},
    {35, 37, 40},
    {32, 36, 38},
    {16, 18, 22}
};*/

struct locker_pins usable_pins[] = {
    {00, 02, 03},
    {21, 22, 23},
    {24, 25, 29},
    {26, 27, 28},
    {04, 05, 06}
};

//This function initializes a locker
void init_locker(struct locker *l, int locker_num, const nfc_connstring device, nfc_context *context) {
	(*l).locked = false; //set the locked variable to false
	printf("set locked false\n");
	(*l).lockerNum = locker_num;
	//free((*l).key);

	printf("getting space for key\n");
	l->key = malloc(KEY_SIZE);
	//printf("key = %x\n", (*l).key);

	printf("Assigning pins\n");
	(*l).LockerPins = &(usable_pins[locker_num]);

    printf("Setting up pins\n");
	// set all pins to output mode
	pinMode((*l).LockerPins->pin_strike_lock, OUTPUT);
	pinMode((*l).LockerPins->pin_led_green, OUTPUT);
	pinMode((*l).LockerPins->pin_led_red, OUTPUT);
	printf("set pins to output\n");

	// initialize pins to a default state
	digitalWrite((*l).LockerPins->pin_strike_lock, LOW);
	digitalWrite((*l).LockerPins->pin_led_green, HIGH);
	digitalWrite((*l).LockerPins->pin_led_red, LOW);

	(*l).reader = nfc_open(context, device);
	(*l).context = context;
	(*l).active = true;
	total_num_lockers++;
}

//This function initializes an array of lockers
void init_lockers(struct locker* l, int locker_count, nfc_connstring devices[], nfc_context *context) {
    int i;
    total_num_lockers = 0;
	for(i = 0; i < locker_count; i++)
	{
	    printf("Initializing locker %d\n", i);
		init_locker(&l[i], i, devices[i], context);
		printf("Finished initializing locker %d\n", i);
	}
}

//This function compares a passed in char array with a lockers key
int compare_key(char* key, struct locker *l) {
    int i;
    for (i = 0; i < KEY_SIZE; i++)
    {
        if (key[i] != l->key[i])
            return -1;
    }
	return 0; //zero if the strings are equal and non-zero if they are not
}

void erase_key(struct locker *l)
{
    int i;
    //free ((*l).key);
    //(*l).key = NULL;

    for (i = 0; i < KEY_SIZE; i++)
        (*l).key[i] = 0x00;

}

void lock_locker(struct locker *l, char *key)
{
    (*l).locked = true;
    //if ((*l).key == NULL)
    //    (*l).key = malloc(KEY_SIZE);

    (*l).key = key;

    digitalWrite((*l).LockerPins->pin_strike_lock, HIGH);
	digitalWrite((*l).LockerPins->pin_led_green, LOW);
	digitalWrite((*l).LockerPins->pin_led_red, HIGH);
}

void unlock_locker(struct locker *l)
{
    (*l).locked = false;
    erase_key(l);
    digitalWrite((*l).LockerPins->pin_strike_lock, LOW);
	digitalWrite((*l).LockerPins->pin_led_green, HIGH);
	digitalWrite((*l).LockerPins->pin_led_red, LOW);
}

//This function will change the state of the locker
void change_locker_state(struct locker *l) {
	if((*l).locked)//if the locker was locked
	{
		(*l).locked = false;
		erase_key(l);
	}
	else
	{
		(*l).locked = true; //set locked to true
		//(*l).key = generate_key();  //generate a key for it
	}
}

void blink_red_led(struct locker *l, int blink_rate, int cycles) // blink_rate is in ms
{
    int i;
    for (i = 0; i < cycles; i++)
    {
        digitalWrite((*l).LockerPins->pin_led_red, HIGH);
        delay(blink_rate);
        digitalWrite((*l).LockerPins->pin_led_red, LOW);
        delay(blink_rate);
    }

    if ((*l).locked)
        digitalWrite((*l).LockerPins->pin_led_red, HIGH);
}

void free_locker_mem(struct locker *l)
{
    printf("Freeing locker memory\n");
    //printf("freeing key = %x\n", l->key);
    free(l->key);
}

void free_lockers_mem(struct locker *lockers, int locker_count)
{
    int i;
    printf("Lockers[0].active = %d\n", lockers[0].active);
    for (i = 0; i < locker_count; i++)
        free_locker_mem(&lockers[i]);
}
